/*
 * TDS PEC 4
 * Grupo 3H2M
 * 
 * Luis Rodríguez-Manzaneque Sánchez
 *
 * El paquete <code>edu.uoc.tds.pec4.server</code> agrupa todas las clases
 * que encapsulan la implementación de los métodos de acceso RMI y el servidor.
 */
package edu.uoc.tds.pec4.server;

import edu.uoc.tds.pec4.server.impl.GestorConexionImpl;
import edu.uoc.tds.pec4.server.impl.GestorAulasImpl;
import edu.uoc.tds.pec4.rmi.GestorAulasInterface;
import edu.uoc.tds.pec4.server.impl.GestorDiccionarioImpl;
import edu.uoc.tds.pec4.rmi.GestorDiccionarioInterface;
import edu.uoc.tds.pec4.rmi.GestorConexionInterface;
import edu.uoc.tds.pec4.common.components.TDSFieldSet;
import edu.uoc.tds.pec4.common.util.TDSLanguageUtils;
import edu.uoc.tds.pec4.server.impl.GestorEstadisticasImpl;
import edu.uoc.tds.pec4.rmi.GestorEstadisticasInterface;
import edu.uoc.tds.pec4.server.impl.GestorMantenimientoImpl;
import edu.uoc.tds.pec4.rmi.GestorMantenimientoInterface;
import java.awt.Color;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.MalformedURLException; 
import java.rmi.ConnectException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.WindowConstants;

/**
 * La clase <code>Servidor</code> representa la interfaz de usuario para
 * iniciar el servidor y permitir el establecimiento de la conexión RMI.<br />
 *
 * Interficie de usuario para iniciar o detener al servidor de conexión RMI.
 *
 * @author	Luis Rodríguez-Manzaneque Sánchez
 * @version	21/11/2011
 * @see		edu.uoc.tds.pec4.common.GestorConexionInterface
 * @see		edu.uoc.tds.pec4.common.GestorDiccionarioInterface
 * @see		edu.uoc.tds.pec4.common.GestorAulasInterface
 * @see		edu.uoc.tds.pec4.common.GestorMantenimientoInterface
 * @see		edu.uoc.tds.pec4.common.GestorEstadisticasInterface
 */
public class Servidor extends javax.swing.JFrame {

    //====================================================== campos
    //... componentes gráficos
    private JPanel jContentPane;
    private TDSFieldSet panelInfo;
    private JButton cmdIniciar;
    private JButton cmdParar;
    private JLabel lblEstado;

    /** servStart Indica si el servidor se encuentra arrancado */
    private boolean servStart = false;

    //... objetos
    /** objRemoto Es el objeto empleado como interfaz en la comunicación RMI */
    private GestorConexionInterface objRemoto = null;

    /** objRemotoDiccionario Es el objeto empleado como interfaz en la comunicación RMI 
     para la obtención de listados maestros*/
    private GestorDiccionarioInterface objRemotoDiccionario = null;
    
    /** objRemotoAulas Es el objeto empleado como interfaz en la comunicación RMI
     para servir las operaciones del subsistema Aulas */
    private GestorAulasInterface objRemotoAulas = null;
    
    /** objRemotoMantenimiento Es el objeto empleado como interfaz en la 
     * comunicación RMI para servir las operaciones del subsistema Mantenimiento
     */
    private GestorMantenimientoInterface objRemotoMantenimiento = null;
    
    /** objRemotoRanking Es el objeto empleado como interfaz en la 
     * comunicación RMI para servir las operaciones del subsistema Estadísticas
     * relativas a los informes de Rankings
     */
    private GestorEstadisticasInterface objRemotoRanking = null;

    /**
     * Constructor de la clase.<br />
     * Es el encargado de cargar el fichero de mensajes i18N y mostrar la infertaz
     * gráfica de usuario.
     */
    public Servidor() {
        //Cargamos el fichero de mensajes
        cargarFicheroMensajes();

        // Inicializamos las etiquetas de los componentes
        inicializarComponentes();

        setEstado();
    }

    /**
     * Carga el fichero de mensajes i18n
     */
    private void cargarFicheroMensajes() {
        /**
         * Comprobar que existe fichero mensajes
         */
        if (!TDSLanguageUtils.setDefaultLanguage("i18n/messages")) {
            System.out.println("No se ha cargado (o no se encuentra) el fichero de mensajes 'i18n/messages*.properties'. La aplicación no se puede iniciar");
            System.exit(-1);
        }

    }

    /**
     * Inicializa y situa los componentes de la GUI
     */
    private void inicializarComponentes()
    {
        jContentPane = null;
        cmdIniciar = null;
        cmdParar = null;
        panelInfo = null;
        lblEstado = null;

        //Creamos y vinculamos los componentes
        this.setContentPane(getJContentPane());

        this.setSize(487, 166);
        this.setLocation(new Point(320, 100));
        this.setResizable(false);
        this.setTitle(TDSLanguageUtils.getMessage("servidor.titulo"));

        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    }

    /**
     * Este método actualiza la etiqueta que informa del estado del servidor
     */
    private void setEstado() {
        if (!servStart) {
            lblEstado.setText(TDSLanguageUtils.getMessage("servidor.estado.pendiente"));
            lblEstado.setForeground(new Color(255, 51, 51));
            cmdIniciar.setEnabled(true);
            cmdParar.setEnabled(false);
        } else {
            lblEstado.setText(TDSLanguageUtils.getMessage("servidor.estado.iniciado"));
            lblEstado.setForeground(new Color(51, 51, 252));
            cmdIniciar.setEnabled(false);
            cmdParar.setEnabled(true);
        }
    }

    /**
     * Arrancada del servidor de RMI
     *
     * @throws  RemoteException En caso de producirse un error de
     *          comunicaciones con el servidor remoto
     * @throws  MalformedURLException Si la URL no está bien formada
     * @throws  ConnectException En caso de producirse un error de conexión
     */
    private void arrancaServidor() throws RemoteException,
            MalformedURLException, ConnectException {
        if (objRemoto == null) {
            iniciarObjectoRemoto();
        }

        Naming.rebind("GestorInterface", objRemoto);
        Naming.rebind("GestorDiccionario", objRemotoDiccionario);
        Naming.rebind("GestorAulas", objRemotoAulas);
        Naming.rebind("GestorMantenimiento",objRemotoMantenimiento);
        Naming.rebind("GestorRanking",objRemotoRanking);
        servStart = true;
        setEstado();
    }

    /**
     * Parada del servidor de RMI
     *
     * @throws  RemoteException En caso de producirse un error de
     *          comunicaciones con el servidor remoto
     * @throws  MalformedURLException Si la URL no está bien formada
     * @throws  NotBoundException
     */
    private void pararServidor() throws RemoteException, MalformedURLException,
                    NotBoundException {
            Naming.unbind("GestorInterface");
            Naming.unbind("GestorDiccionario");
            Naming.unbind("GestorAulas");
            Naming.unbind("GestorMantenimiento");
            Naming.unbind("GestorRanking");
            servStart = false;
            setEstado();
    }

    /**
     * Inicializa el objeto remoto, en caso de que no se haya hecho antes.
     *
     * @throws  RemoteException En caso de no poder establecer la comunicación.
     */
    private void iniciarObjectoRemoto() throws RemoteException {
        servStart = false;

        if (objRemoto == null) {
            objRemoto = new GestorConexionImpl();
            objRemotoDiccionario = new GestorDiccionarioImpl();
            objRemotoAulas = new GestorAulasImpl();
            objRemotoMantenimiento = new GestorMantenimientoImpl();
            objRemotoRanking = new GestorEstadisticasImpl();
        }
    }

    /**
     * Muestra en GUI el botón de iniciar las comunicaciones
     */
    private JButton getCmdIniciar()
    {
        if(cmdIniciar == null)
        {
            cmdIniciar = new JButton();
            cmdIniciar.setBounds(new Rectangle(27, 80, 202, 40));
            cmdIniciar.setText(TDSLanguageUtils.getMessage("servidor.iniciar"));
            cmdIniciar.addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent evt)
                {
                    cmdIniciarActionPerformed(evt);
                }
            });
        }
        return cmdIniciar;
    }

    /**
     * Muestra en GUI el botón de detener las comunicaciones
     */
    private JButton getCmdParar()
    {
        if(cmdParar == null)
        {
            cmdParar = new JButton();
            cmdParar.setBounds(new Rectangle(255, 80, 202, 40));
            cmdParar.setText(TDSLanguageUtils.getMessage("servidor.parar"));
            cmdParar.addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent evt)
                {
                    cmdPararActionPerformed(evt);
                }
            });
        }
        return cmdParar;
    }

    /**
     * Método que maneja el evento sobre el botón de Iniciar.<br />
     * Intenta arrancar el servidor, contrlando las posibles excepciones.
     */
    private void cmdIniciarActionPerformed(java.awt.event.ActionEvent evt) {
        try {
            arrancaServidor();
        } catch (RemoteException eR) {
            JOptionPane.showMessageDialog(null, TDSLanguageUtils.getMessage("servidor.error.rmi") + " " + eR.getMessage(),
                    TDSLanguageUtils.getMessage("servidor.error"),
                    JOptionPane.ERROR_MESSAGE);
        } catch (MalformedURLException eMurl) {
            // path incorrecto
            JOptionPane.showMessageDialog(null, TDSLanguageUtils.getMessage("servidor.error.rmi") + " " + eMurl.getMessage(),
                    TDSLanguageUtils.getMessage("servidor.error"),
                    JOptionPane.ERROR_MESSAGE);
        } catch (Exception eV) {
            // error desconectado
            JOptionPane.showMessageDialog(null, eV.toString(),
                    TDSLanguageUtils.getMessage("servidor.error"),
                    JOptionPane.ERROR_MESSAGE);
        }
    }

    /**
     * Método que maneja el evento sobre el botón de Detener.<br />
     * Intenta detener el servidor, contrlando las posibles excepciones.
     */
    private void cmdPararActionPerformed(java.awt.event.ActionEvent evt) {
        try {
            pararServidor();
        } catch (RemoteException eRe) {
            JOptionPane.showMessageDialog(null, TDSLanguageUtils.getMessage("servidor.error.fin.ok"),
                    TDSLanguageUtils.getMessage("servidor.error"),
                    JOptionPane.ERROR_MESSAGE);
        } catch (MalformedURLException eMurle) {
            // path incorrecto
            JOptionPane.showMessageDialog(null, TDSLanguageUtils.getMessage("servidor.error.fin"),
                    TDSLanguageUtils.getMessage("servidor.error"),
                    JOptionPane.ERROR_MESSAGE);
        } catch (NotBoundException eNbe) {
            // error
            JOptionPane.showMessageDialog(null, TDSLanguageUtils.getMessage("servidor.error.fin"),
                    TDSLanguageUtils.getMessage("servidor.error"),
                    JOptionPane.ERROR_MESSAGE);
        } catch (Exception eE) {
            // error indeterminado
            JOptionPane.showMessageDialog(null, eE.toString(),
                    TDSLanguageUtils.getMessage("errors"),
                    JOptionPane.ERROR_MESSAGE);
        }
    }

    /**
     * Devuelve un panel de la GUI que muestra una etiqueta con el estado del servidor:<br />
     * Pendiente o iniciado
     */
    private JPanel getPanelInfo()
    {
        if(panelInfo == null)
        {
            lblEstado = new JLabel();
            lblEstado.setText(TDSLanguageUtils.getMessage("servidor.estado.pendiente"));
            lblEstado.setForeground(new Color(0, 0, 255));
            lblEstado.setDisplayedMnemonic(0);

            panelInfo = new TDSFieldSet();
            panelInfo.setLayout(new GridBagLayout());
            panelInfo.setBounds(new Rectangle(27, 15, 425, 50));
            panelInfo.setTitulo(TDSLanguageUtils.getMessage("servidor.panel.titulo"));
            panelInfo.add(lblEstado, null);

        }
        return panelInfo;
    }

    /**
     * Devuelve el panel principal de la GUI que contiene al resto de
     * componentes a mostrar
     *
     * @return  Devuelve un <code>JPanel</code> con toda la disposición de controles
     *          de usuario.
     */
    private JPanel getJContentPane()
    {
        if(jContentPane == null)
        {
            jContentPane = new JPanel();
            jContentPane.setLayout(null);
            jContentPane.add(getCmdIniciar(), null);
            jContentPane.add(getCmdParar(), null);
            jContentPane.add(getPanelInfo(), null);
        }
        return jContentPane;
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() { 
                Servidor objServidor = new Servidor();
                objServidor.setLocation(300, 100);
                objServidor.setResizable(false);
                objServidor.setVisible(true);
            }
        });
    }
}